package cn.wolfcode.web.controller;

import cn.wolfcode.common.domain.UserInfo;
import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.common.web.anno.RequireLogin;
import cn.wolfcode.domain.OrderInfo;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.mq.MQConstant;
import cn.wolfcode.mq.OrderMessage;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.util.DateUtil;
import cn.wolfcode.util.UserUtil;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ConcurrentHashMap;


@RestController
@RequestMapping("/order")
@Slf4j
public class OrderInfoController {
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private IOrderInfoService orderInfoService;
    public static ConcurrentHashMap<Long, Boolean> local_flag = new ConcurrentHashMap<>();

    @PostMapping("/doSeckill")
    @RequireLogin // 1.判断用户是否登录
    // 返回一个订单编号
    public Result<String> doSeckill(int time, Long seckillId, HttpServletRequest request) {

        // 2.参数校验
        if (StringUtils.isEmpty(time + "") || StringUtils.isEmpty(seckillId + "")) {
            throw new BusinessException(SeckillCodeMsg.OPERATION_ERROR);    // 抛出违法操作信息
        }

        // 判断本地标识   1/2号
        Boolean localFlag = local_flag.get(seckillId);
        if (localFlag != null && localFlag) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }

        // 3.判断是否在秒杀活动时间内
        // 获取单个VO信息使用find方法,去redis中
        SeckillProductVo seckillProductVo = seckillProductService.find(time, seckillId);
//        boolean flag = DateUtil.isLegalTime(seckillProductVo.getStartDate(), time);
//        if (!flag) {    // 不在活动时间内
//            throw new BusinessException(SeckillCodeMsg.OPERATION_ERROR);    // 抛出违法操作信息
//        }

        // 4.判断库存是否足够
        if (seckillProductVo.getStockCount() < 0) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);     // 您来晚了
        }

        // 5.判断用户是否有重复下单
        // 使用set 	seckillOrderSet:time  phone:seckillId  isMember

//        // 减少redis中的库存  1/2号
//        Long count = redisTemplate.opsForHash().increment(SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(time + ""), seckillId + "", -1);
//        if (count < 0) {
//            // redis 预库存已经减到负数,已经满人数了
//            local_flag.put(seckillId,true);     // 标识变为true
//            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);      // 您来晚了
//        }


        String token = request.getHeader("token");
        UserInfo user = UserUtil.getUser(redisTemplate, token);
        Boolean flag = redisTemplate.opsForSet().isMember(SeckillRedisKey.SECKILL_ORDER_SET.getRealKey(time + ""), user.getPhone() + ":" + seckillId);
        if (flag) { // 返回true则用户已经抢购过
            throw new BusinessException(SeckillCodeMsg.REPEAT_SECKILL);       // 请不要重复抢购
        }

        // 减少redis中的库存  1/2号
        Long count = redisTemplate.opsForHash().increment(SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(time + ""), seckillId + "", -1);
        if (count < 0) {
            // redis 预库存已经减到负数,已经满人数了
            local_flag.put(seckillId,true);     // 标识变为true
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);      // 您来晚了
        }

        // 6.秒杀业务逻辑

//        String orderNo=orderInfoService.doSeckill(time, seckillId, user.getPhone());   // 返回的是订单编号, 秒杀1.0的版本没有涉及MQ
//        return Result.success("订单编号:"+orderNo);

        // 异步下单流程图第1.2步
        // 把数据封装成消息发送给MQ中
        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setTime(time);
        orderMessage.setSeckillId(seckillId);
        orderMessage.setToken(token);
        orderMessage.setUserPhone(user.getPhone());     // 使用用户信息获取手机号
        rocketMQTemplate.sendOneWay(MQConstant.ORDER_PEDDING_TOPIC,orderMessage);                  // 使用RocketMQ发送一次性消息,第一次消息进入订单队列中,消息就是orderMessage
        return Result.success("正在抢购商品,请稍等...");
    }

    @GetMapping("/find")    // 返回订单
    public Result<OrderInfo> find(String orderNo,HttpServletRequest request) {
        if (StringUtils.isEmpty(orderNo)) {
            throw new BusinessException(SeckillCodeMsg.OPERATION_ERROR);
        }
        OrderInfo orderInfo = orderInfoService.find(orderNo);
        if (orderInfo == null) {
            throw new BusinessException(SeckillCodeMsg.OPERATION_ERROR);
        }

        String token = request.getHeader("token");                  // 请求头中获取token
        UserInfo user = UserUtil.getUser(redisTemplate, token);         // 获取用户
        if (!user.getPhone().equals(orderInfo.getUserId())) {
            throw new BusinessException(SeckillCodeMsg.OPERATION_ERROR);
        }

        return Result.success(orderInfo);    // 成功,返回订单信息
    }
}
